package cn.imvc.interceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.alibaba.druid.util.StringUtils;
import com.github.sd4324530.fastweixin.api.OauthAPI;
import com.github.sd4324530.fastweixin.api.config.ApiConfig;
import com.github.sd4324530.fastweixin.api.enums.OauthScope;

import java.io.IOException;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import cn.imvc.app.commons.SystemConfig;
import cn.imvc.app.domains.Constants;
import cn.imvc.app.entities.Member;
import cn.imvc.app.models.MemberModel;
import cn.imvc.core.ICache;
import cn.imvc.core.SubmitVerify;
import cn.imvc.util.CookieTools;
import cn.imvc.util.Md5;
import cn.imvc.util.Wechat;

public class SubmitVerifyInterceptor extends HandlerInterceptorAdapter {
	private static final Logger LOG = Logger.getLogger(SubmitVerifyInterceptor.class);

	@Autowired
	ICache cache;

	@Autowired
	Wechat wechat;

	@Autowired
	MemberModel memberModel;
	
	@Autowired
	SystemConfig systemConfig;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		String token = request.getParameter("token");
		if (token != null && !token.isEmpty()) {
			Member member = cache.get(Constants.CACHENAME_MEMBER, token);
			if (member != null) {
				cache.put(Constants.CACHENAME_MEMBER, token, member, Constants.TOKEN_INDATE);
			}
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			Method method = handlerMethod.getMethod();
			SubmitVerify annotation = method.getAnnotation(SubmitVerify.class);
			if (annotation != null) {
				boolean saveVerify = annotation.create();
				if (saveVerify) {
					String verify = generateVerify(token);
					request.getSession().setAttribute("verify", verify);
					cache.put("verify", verify, verify, 7200);
				}
				boolean removeVerify = annotation.check();
				if (removeVerify) {
					if (isRepeatSubmit(request.getParameter("verify"))) {
						LOG.warn("please don't repeat submit,[token:" + token + ",url:" + request.getServletPath()
								+ "]");
						return false;
					}
					cache.remove("verify", request.getParameter("verify"));
					request.getSession(false).removeAttribute("verify");
				}
			}
		}

		if(request.getHeader("user-agent")==null){
			return true;
		}
		String ua =request.getHeader("user-agent").toLowerCase();
		String url=request.getServletPath();
		if (ua.indexOf("micromessenger") > 0 && (url.contains("/index.jsp")||url.contains("/member")||url.contains("/center") || url.contains("/red/index")) ) {
			Cookie userAccessToken = CookieTools.getCookieByName(request, "user_access_token");
			if (userAccessToken == null) {
				return wechatAuth(request, response);
			} else {
				String openid = cache.getSecond("WEIXIN_CACHE", userAccessToken.getValue());
				// openid改为unionid
				openid = cache.getSecond("WEIXIN_CACHE_USERINFO", openid + "uid");
				if (openid == null || openid.isEmpty()) {
					return wechatAuth(request, response);
				} else {
					// 注册或绑定手机号之前需要获取验证码，此步骤不需要拦截
					String servletPath = request.getServletPath();
					
					if(!StringUtils.isEmpty(servletPath) && (servletPath.contains("/member/sendCode") || servletPath.contains("getImageCode"))){
						return true;
					}
					Member member = null;
					// token 为空或者失效
					if(StringUtils.isEmpty(token) || "undefined".equalsIgnoreCase(token)){
						member = memberModel.findByUnionid(openid);
						if (member == null) {
							
							if(!url.contains("/index.jsp")){
							response.sendRedirect("http://www.xinghaoshangcheng.com/wechat/reglogin.html?url=http://www.xinghaoshangcheng.com" + servletPath + "&type=open");
							return false;
							}else{
								return true;
							}
						} else {
							String clientToken = Md5.encode(member.getLoginname() + String.valueOf(System.currentTimeMillis()));
							cache.put(Constants.CACHENAME_MEMBER, clientToken, member, Constants.TOKEN_INDATE);
							CookieTools.addCookie(response, "token", Constants.DOMAIN_SUFFIX.substring(1), clientToken, -1);
							String concat = "?";
							if (servletPath.indexOf("?") > 0) {
								concat = "&";
							}
							request.getRequestDispatcher(servletPath + concat + "token=" + clientToken).forward(request, response);
							return false;
						}
					} else {
						// 判断缓存是否失效
						member = cache.get(Constants.CACHENAME_MEMBER, token);
						if(member == null){
							member = memberModel.findByUnionid(openid);
							if (member == null) {
								if(!url.contains("/index.jsp")){
								response.sendRedirect("http://www.xinghaoshangcheng.com/wechat/reglogin.html?url=http://www.xinghaoshangcheng.com" + servletPath + "&type=open");
								return false;
								}else{
									return true;
								}
							}
						}
						cache.put(Constants.CACHENAME_MEMBER, token, member, Constants.TOKEN_INDATE);
					}
				}
			}
		}
		return true;
	}

	private boolean wechatAuth(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String domain = request.getServerName();
		OauthAPI oauth = new OauthAPI(new ApiConfig(wechat.getAppId(),wechat.getAppSecret()));
		
		String url=request.getServletPath();
		if(url.contains("login.html")||url.contains("register.html")){
			
			url="http://www.xinghaoshangcheng.com/index.html";
		}
		String authUrl = oauth.getOauthPageUrl("http://www.xinghaoshangcheng.com/wechat/auth.html?url="+url+"&domain="+domain, OauthScope.SNSAPI_USERINFO, "authAop");
		response.sendRedirect(authUrl);
		return false;
	}

	private boolean isRepeatSubmit(String clinetVerify) {

		String verify = cache.get("verify", clinetVerify);
		if (verify == null) {
			return true;
		}
		if (clinetVerify == null) {
			return true;
		}
		if (!verify.equals(clinetVerify)) {
			return true;
		}
		return false;
	}

	private String generateVerify(String token) {
		try {
			byte id[] = token.getBytes();
			long current = System.currentTimeMillis();
			byte now[] = new Long(current).toString().getBytes();
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(id);
			md.update(now);
			return toHex(md.digest());
		} catch (NoSuchAlgorithmException e) {
			return null;
		}

	}

	private String toHex(byte buffer[]) {
		StringBuffer sb = new StringBuffer(buffer.length * 2);
		for (int i = 0; i < buffer.length; i++) {
			sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
			sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
		}
		return sb.toString();
	}
}